Displaying Lists Using FlatList and SectionList in React Native
Course: React Native Training
Topic: Displaying Lists Using FlatList and SectionList
Course Link: React Native Training Course
Demo Registration: Register for a Course Demo
JustAcademy: Visit JustAcademy
1. Introduction to Lists in React Native
Lists are an essential part of mobile application interfaces. Applications use lists to display products, contacts, messages, notifications, courses, transactions, tasks, and other collections of information.
React Native provides two important components for displaying scrollable collections: FlatList and SectionList. Both use virtualized rendering to help display large datasets efficiently rather than mounting every row at once.
- FlatList: Displays a single collection of items in a scrollable list.
- SectionList: Displays items organized into groups, with optional headings and footers for each section.
For long collections, these components are generally preferable to rendering every item inside a regular ScrollView. Learn more about list views in React Native.
Learning Objectives
- Understand the purpose of FlatList and SectionList.
- Display arrays and objects as list items.
- Use data, sections, renderItem, and keyExtractor.
- Style list rows and section headings.
- Implement separators, headers, footers, and empty states.
- Handle item presses and selection.
- Update list data using React state.
- Implement refreshing and pagination.
- Improve list performance and troubleshoot common errors.
2. What Is FlatList?
FlatList is a built-in React Native component for displaying a scrollable collection of similarly structured items. It is useful when the number of records may change or the list contains many items.
Common Use Cases
- Contact directories.
- Product catalogs.
- Chat messages and notifications.
- Search results.
- Course listings.
- Task managers and transaction histories.
Basic FlatList Example
import React from 'react';
import { View, Text, FlatList } from 'react-native';
const students = [
{ id: '1', name: 'Aarav' },
{ id: '2', name: 'Priya' },
{ id: '3', name: 'Rahul' }
];
export default function StudentList() {
return (
<View style={{ flex: 1, padding: 16 }}>
<FlatList
data={students}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Text style={{ padding: 12 }}>
{item.name}
</Text>
)}
/>
</View>
);
}
Code Explanation
students is an array containing student records.
data supplies the array to FlatList.
renderItem describes the UI for each student.
item represents the current record.
keyExtractor returns a unique key for each row.
- FlatList manages the scrollable list and virtualized rendering.
3. Understanding the Main FlatList Props
| Prop |
Purpose |
Example |
data |
Provides the list items. |
data={students} |
renderItem |
Defines how each item is displayed. |
renderItem={({ item }) => ...} |
keyExtractor |
Returns a stable key for each item. |
keyExtractor={item => item.id} |
horizontal |
Displays items horizontally. |
horizontal={true} |
ListHeaderComponent |
Displays content before the list rows. |
ListHeaderComponent={Header} |
ListFooterComponent |
Displays content after the list rows. |
ListFooterComponent={Footer} |
ItemSeparatorComponent |
Renders a divider between rows. |
ItemSeparatorComponent={Separator} |
ListEmptyComponent |
Displays content when the list is empty. |
ListEmptyComponent={EmptyState} |
numColumns |
Displays items in multiple columns. |
numColumns={2} |
onEndReached |
Runs when scrolling approaches the end. |
onEndReached={loadMore} |
onRefresh |
Handles pull-to-refresh actions. |
onRefresh={refreshData} |
refreshing |
Controls the refresh indicator. |
refreshing={isRefreshing} |
extraData |
Signals changes to external rendering dependencies. |
extraData={selectedId} |
getItemLayout |
Provides known dimensions and offsets for fixed-size items. |
getItemLayout={getLayout} |
4. Understanding data and renderItem
The data prop supplies the records, and renderItem defines how each record appears. The callback receives an object that includes the current item and its index.
const courses = [
{ id: '101', title: 'React Native', duration: '6 weeks' },
{ id: '102', title: 'JavaScript', duration: '4 weeks' },
{ id: '103', title: 'React JS', duration: '5 weeks' }
];
<FlatList
data={courses}
keyExtractor={item => item.id}
renderItem={({ item, index }) => (
<View style={{ padding: 12 }}>
<Text>{index + 1}. {item.title}</Text>
<Text>Duration: {item.duration}</Text>
</View>
)}
/>
The index starts at zero, so index + 1 displays numbering beginning at one. Use a stable ID for the key rather than the array index when items may be inserted, removed, or reordered.
5. Why keyExtractor Is Important
React uses keys to identify individual rows between renders. Stable, unique keys help React understand which items have changed, moved, or been removed.
<FlatList
data={students}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Text>{item.name}</Text>
)}
/>
Key Best Practices
- Use a unique identifier from the data whenever possible.
- Keep the key stable when a record is edited or reordered.
- Avoid using array indexes as keys for changing lists.
- Do not generate a new random key during every render.
- Make sure each key is unique within the relevant list.
FlatList can use an item's key or id by default, but an explicit keyExtractor makes the intended key behavior clear.
6. Styling FlatList Items
Each row can contain View, Text, Image, Pressable, and other React Native components. StyleSheet helps keep layout and visual formatting consistent.
import React from 'react';
import {
FlatList,
Text,
View,
StyleSheet
} from 'react-native';
const products = [
{ id: '1', name: 'Wireless Headphones', price: '₹1,499' },
{ id: '2', name: 'Bluetooth Speaker', price: '₹2,199' },
{ id: '3', name: 'Smart Watch', price: '₹3,499' }
];
export default function ProductList() {
return (
<FlatList
data={products}
keyExtractor={item => item.id}
contentContainerStyle={styles.list}
renderItem={({ item }) => (
<View style={styles.card}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.price}>{item.price}</Text>
</View>
)}
/>
);
}
const styles = StyleSheet.create({
list: {
padding: 16
},
card: {
padding: 16,
marginBottom: 12,
borderRadius: 10,
backgroundColor: '#F3F4F6'
},
name: {
fontSize: 17,
fontWeight: '600'
},
price: {
marginTop: 6,
fontSize: 15,
color: '#166534'
}
});
Each product is rendered as a card with its name and price. Keeping styles in a StyleSheet improves readability and makes visual changes easier to manage.
7. Adding Separators Between Items
The ItemSeparatorComponent prop renders a separator between list rows. Separators make long lists easier to scan without requiring a separate card for every item.
const Separator = () => (
<View
style={{
height: 1,
backgroundColor: '#D1D5DB'
}}
/>
);
<FlatList
data={students}
keyExtractor={item => item.id}
ItemSeparatorComponent={Separator}
renderItem={({ item }) => (
<Text style={{ padding: 14 }}>{item.name}</Text>
)}
/>
The separator is rendered between items, not before the first item or after the last item. SectionList also supports section separators, which serve a different purpose.
8. Using List Headers and Footers
Headers and footers add contextual information at the beginning or end of a list. They can contain a title, instructions, totals, or a message indicating that the user has reached the end.
<FlatList
data={products}
keyExtractor={item => item.id}
ListHeaderComponent={
<Text style={{ fontSize: 22, fontWeight: 'bold', padding: 16 }}>
Available Products
</Text>
}
ListFooterComponent={
<Text style={{ textAlign: 'center', padding: 16 }}>
You have reached the end.
</Text>
}
renderItem={({ item }) => (
<Text style={{ padding: 12 }}>{item.name}</Text>
)}
/>
You can supply a React element or a component to these props. Keep headers and footers lightweight, especially when they contain changing data.
9. Handling Empty Lists
When a list has no data, display a useful message instead of leaving a blank screen. The ListEmptyComponent prop is useful when a search returns no results or when a user has not created any records.
const EmptyState = () => (
<View style={{ padding: 24, alignItems: 'center' }}>
<Text style={{ fontSize: 18, fontWeight: '600' }}>
No items found
</Text>
<Text style={{ marginTop: 8 }}>
Try changing your search or adding an item.
</Text>
</View>
);
<FlatList
data={[]}
keyExtractor={item => item.id}
renderItem={({ item }) => <Text>{item.name}</Text>}
ListEmptyComponent={EmptyState}
/>
Keep loading, empty, and error states separate. An empty message should not be shown while data is still being fetched.
10. Creating a Horizontal List
Setting horizontal to true displays items from left to right. This is useful for category selectors, featured products, image galleries, and recommendations.
<FlatList
horizontal
data={categories}
keyExtractor={item => item.id}
showsHorizontalScrollIndicator={false}
renderItem={({ item }) => (
<View
style={{
padding: 16,
marginRight: 10,
backgroundColor: '#E5E7EB',
borderRadius: 10
}}
>
<Text>{item.name}</Text>
</View>
)}
/>
11. Creating a Grid with FlatList
The numColumns prop displays a list in multiple columns. It is commonly used for product grids, photo galleries, category tiles, and dashboard shortcuts.
<FlatList
data={products}
keyExtractor={item => item.id}
numColumns={2}
columnWrapperStyle={{ justifyContent: 'space-between' }}
contentContainerStyle={{ padding: 12 }}
renderItem={({ item }) => (
<View
style={{
flex: 1,
margin: 6,
padding: 16,
minHeight: 100,
borderRadius: 8,
backgroundColor: '#E5E7EB'
}}
>
<Text style={{ fontWeight: '600' }}>{item.name}</Text>
<Text>{item.price}</Text>
</View>
)}
/>
FlatList supports multiple columns for vertical lists. Items in the same row should have compatible heights; this is not a masonry layout. See the official FlatList documentation.
12. What Is SectionList?
SectionList is a React Native component for displaying items grouped into sections. Each section can have a heading, such as a category, date, department, or alphabet letter.
Common Use Cases
- Contacts grouped alphabetically.
- Messages grouped by date.
- Transactions grouped by month.
- Products grouped by category.
- Settings grouped by topic.
- Schedules grouped by day.
Basic Section Data Structure
const sections = [
{
title: 'Fruits',
data: ['Apple', 'Banana', 'Orange']
},
{
title: 'Vegetables',
data: ['Carrot', 'Spinach', 'Potato']
}
];
Each section normally contains a data array. Other fields, such as title or date, can store metadata used by your rendering functions.
13. Basic SectionList Example
import React from 'react';
import {
View,
Text,
SectionList,
StyleSheet
} from 'react-native';
const sections = [
{
title: 'Fruits',
data: ['Apple', 'Banana', 'Orange']
},
{
title: 'Vegetables',
data: ['Carrot', 'Spinach', 'Potato']
},
{
title: 'Drinks',
data: ['Water', 'Juice', 'Milk']
}
];
export default function FoodList() {
return (
<View style={styles.container}>
<SectionList
sections={sections}
keyExtractor={(item, index) => `${item}-${index}`}
renderSectionHeader={({ section }) => (
<Text style={styles.header}>{section.title}</Text>
)}
renderItem={({ item }) => (
<Text style={styles.item}>{item}</Text>
)}
ItemSeparatorComponent={() => (
<View style={styles.separator} />
)}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16
},
header: {
padding: 12,
fontSize: 18,
fontWeight: 'bold',
backgroundColor: '#E5E7EB'
},
item: {
padding: 12,
fontSize: 16
},
separator: {
height: 1,
backgroundColor: '#D1D5DB'
}
});
How SectionList Works
sections provides the grouped data.
renderSectionHeader displays each section title.
renderItem displays each item within a section.
keyExtractor identifies individual rows.
ItemSeparatorComponent displays dividers between rows.
In this example, the index is included in the key because food names are only assumed unique within their example section. In production, use stable unique item IDs whenever possible.
14. Understanding SectionList Props
| Prop |
Purpose |
Example |
sections |
Provides the array of grouped sections. |
sections={sections} |
renderItem |
Defines how each item is displayed. |
renderItem={({ item }) => ...} |
renderSectionHeader |
Displays the heading for a section. |
renderSectionHeader={({ section }) => ...} |
renderSectionFooter |
Displays content at the end of a section. |
renderSectionFooter={...} |
keyExtractor |
Provides a key for each item. |
keyExtractor={item => item.id} |
ItemSeparatorComponent |
Separates individual rows. |
ItemSeparatorComponent={Separator} |
SectionSeparatorComponent |
Separates sections. |
SectionSeparatorComponent={Separator} |
ListHeaderComponent |
Displays content before all sections. |
ListHeaderComponent={Header} |
ListFooterComponent |
Displays content after all sections. |
ListFooterComponent={Footer} |
ListEmptyComponent |
Displays content when no items are available. |
ListEmptyComponent={EmptyState} |
stickySectionHeadersEnabled |
Controls whether section headings stick while scrolling. |
stickySectionHeadersEnabled={true} |
onRefresh |
Handles pull-to-refresh. |
onRefresh={refreshData} |
refreshing |
Controls the refresh indicator. |
refreshing={isRefreshing} |
onEndReached |
Handles approaching the end of the list. |
onEndReached={loadMore} |
extraData |
Signals external state changes that affect rendering. |
extraData={selectedId} |
15. Working with Section Metadata
Sections can contain custom metadata, such as a date, description, or item count. Your rendering functions decide how to display this information.
const sections = [
{
title: 'Monday',
date: '17 October',
data: [
{ id: '1', task: 'Review course notes' },
{ id: '2', task: 'Practice React Native' }
]
},
{
title: 'Tuesday',
date: '18 October',
data: [
{ id: '3', task: 'Build a list screen' },
{ id: '4', task: 'Test the application' }
]
}
];
<SectionList
sections={sections}
keyExtractor={item => item.id}
renderSectionHeader={({ section }) => (
<View>
<Text>{section.title}</Text>
<Text>{section.date}</Text>
</View>
)}
renderItem={({ item }) => (
<Text>{item.task}</Text>
)}
/>
The properties title and date are application-defined metadata. SectionList automatically uses the section's data array for its items, but it does not automatically display custom fields.
16. FlatList vs SectionList
| Feature |
FlatList |
SectionList |
| Data structure |
One array of items. |
An array of sections, each with its own data array. |
| Section headings |
No dedicated section header API. |
Supports renderSectionHeader. |
| Best use |
Products, messages, search results, feeds. |
Contacts, schedules, categorized records. |
| Item rendering |
Uses renderItem. |
Uses renderItem and can support per-section renderers. |
| Separators |
Supports item separators. |
Supports item and section separators. |
| Virtualized rendering |
Yes. |
Yes. |
| Pull-to-refresh |
Supported. |
Supported. |
| Grid columns |
Supports numColumns for vertical lists. |
Does not provide the same numColumns grid API as FlatList. |
Which one should you choose? Use FlatList for a single collection. Use SectionList when items are naturally grouped under headings. Both are suitable for scrollable, virtualized lists. FlatList documentation | SectionList documentation.
17. Handling Presses on List Items
Rows can respond to user interactions. Wrap a row in Pressable to handle taps, open details, select a record, or navigate to another screen.
import React from 'react';
import {
FlatList,
Pressable,
Text,
Alert
} from 'react-native';
const products = [
{ id: '1', name: 'Laptop' },
{ id: '2', name: 'Phone' },
{ id: '3', name: 'Headphones' }
];
export default function SelectableList() {
const handlePress = item => {
Alert.alert('Selected product', item.name);
};
return (
<FlatList
data={products}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Pressable
onPress={() => handlePress(item)}
accessibilityRole="button"
style={{ padding: 16 }}
>
<Text>{item.name}</Text>
</Pressable>
)}
/>
);
}
The example displays an alert when a row is tapped. In a production app, the same handler could navigate to a product detail screen or update a shopping cart.
18. Updating List Data with React State
List data often changes when users add, edit, complete, or remove items. Store changing data in React state and create a new array when updating it.
import React, { useState } from 'react';
import {
FlatList,
Text,
View,
Pressable
} from 'react-native';
const initialTasks = [
{ id: '1', title: 'Learn FlatList' },
{ id: '2', title: 'Practice SectionList' }
];
export default function TaskList() {
const [tasks, setTasks] = useState(initialTasks);
const removeTask = id => {
setTasks(currentTasks =>
currentTasks.filter(task => task.id !== id)
);
};
return (
<FlatList
data={tasks}
keyExtractor={item => item.id}
ListEmptyComponent={
<Text>No tasks remaining.</Text>
}
renderItem={({ item }) => (
<View style={{ padding: 12 }}>
<Text>{item.title}</Text>
<Pressable onPress={() => removeTask(item.id)}>
<Text>Remove</Text>
</Pressable>
</View>
)}
/>
);
}
The filter() method creates a new array without the selected task. This immutable update allows React and FlatList to recognize the changed data.
19. Selecting Items in FlatList
Selection is useful when a user must choose a category, mark a preferred option, or select a record for another action.
import React, { useState } from 'react';
import {
FlatList,
Pressable,
Text
} from 'react-native';
const options = [
{ id: '1', label: 'Design' },
{ id: '2', label: 'Development' },
{ id: '3', label: 'Testing' }
];
export default function SelectableOptions() {
const [selectedId, setSelectedId] = useState(null);
return (
<FlatList
data={options}
extraData={selectedId}
keyExtractor={item => item.id}
renderItem={({ item }) => {
const selected = item.id === selectedId;
return (
<Pressable
onPress={() => setSelectedId(item.id)}
style={{
padding: 16,
backgroundColor: selected ? '#DBEAFE' : '#FFFFFF'
}}
accessibilityRole="button"
accessibilityState={{ selected }}
>
<Text>
{selected ? 'Selected: ' : ''}{item.label}
</Text>
</Pressable>
);
}}
/>
);
}
extraData tells FlatList that the selected ID affects the rendered rows. FlatList performs shallow prop comparisons, so changes in external rendering dependencies should be reflected in changed props.
20. Displaying Grouped Data with SectionList
A contact directory grouped by department is a practical example of SectionList. Each section displays a department heading and its employees.
import React from 'react';
import {
SectionList,
Text,
View,
StyleSheet
} from 'react-native';
const departments = [
{
title: 'Development',
data: [
{ id: '1', name: 'Aarav', role: 'React Native Developer' },
{ id: '2', name: 'Priya', role: 'Frontend Developer' }
]
},
{
title: 'Design',
data: [
{ id: '3', name: 'Riya', role: 'UI Designer' },
{ id: '4', name: 'Kabir', role: 'UX Designer' }
]
}
];
export default function EmployeeDirectory() {
return (
<SectionList
sections={departments}
keyExtractor={item => item.id}
renderSectionHeader={({ section }) => (
<Text style={styles.heading}>{section.title}</Text>
)}
renderItem={({ item }) => (
<View style={styles.row}>
<Text style={styles.name}>{item.name}</Text>
<Text>{item.role}</Text>
</View>
)}
/>
);
}
const styles = StyleSheet.create({
heading: {
padding: 12,
backgroundColor: '#E5E7EB',
fontSize: 18,
fontWeight: 'bold'
},
row: {
padding: 14,
borderBottomWidth: 1,
borderBottomColor: '#E5E7EB'
},
name: {
fontSize: 16,
fontWeight: '600'
}
});
This pattern can also be used for courses grouped by subject, transactions grouped by month, and schedules grouped by date.
21. Sticky Section Headers
Sticky headers remain near the top of the screen while the user scrolls through a section. This helps users identify the group they are viewing.
<SectionList
sections={sections}
keyExtractor={(item, index) => `${item.id}-${index}`}
renderSectionHeader={({ section }) => (
<Text>{section.title}</Text>
)}
renderItem={({ item }) => (
<Text>{item.name}</Text>
)}
stickySectionHeadersEnabled={true}
/>
Sticky section headers are enabled by default on iOS and disabled by default on Android. Set the prop explicitly when you want consistent behavior across platforms.
22. Implementing Pull-to-Refresh
Pull-to-refresh allows users to request fresh data by pulling down on a list. FlatList and SectionList support it through the onRefresh and refreshing props.
import React, { useState } from 'react';
import { FlatList, Text } from 'react-native';
export default function RefreshableList() {
const [items, setItems] = useState([
{ id: '1', name: 'First item' },
{ id: '2', name: 'Second item' }
]);
const [refreshing, setRefreshing] = useState(false);
const refreshData = async () => {
setRefreshing(true);
try {
// Replace this example with an API request.
const updatedItems = await fetchLatestItems();
setItems(updatedItems);
} catch (error) {
// Display an appropriate error message.
} finally {
setRefreshing(false);
}
};
return (
<FlatList
data={items}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Text style={{ padding: 16 }}>{item.name}</Text>
)}
refreshing={refreshing}
onRefresh={refreshData}
/>
);
}
fetchLatestItems() is a placeholder for a function you would implement to retrieve fresh data. Ensure it returns an array of items, handles errors appropriately, and always resets the refreshing state.
23. Implementing Pagination and Load More
Pagination retrieves data in smaller batches instead of loading a very large collection all at once. The onEndReached prop can trigger another request when the user approaches the end of the list.
<FlatList
data={items}
keyExtractor={item => item.id}
renderItem={({ item }) => (
<Text style={{ padding: 16 }}>{item.title}</Text>
)}
onEndReached={loadMoreItems}
onEndReachedThreshold={0.5}
ListFooterComponent={
isLoadingMore ? <Text>Loading more...</Text> : null
}
/>
The threshold determines how close to the end the callback can run, relative to the visible list length. Depending on scrolling and layout, the callback may fire more than once, so the pagination handler must prevent duplicate requests.
Pagination Best Practices
- Track the current page number or cursor.
- Prevent concurrent requests for the same page.
- Track whether more results are available.
- Append new items without mutating the existing array.
- Show a loading indicator while fetching more records.
- Handle errors and allow failed requests to be retried.
- Deduplicate items when the data source can return overlapping pages.
24. Performance Optimization
FlatList and SectionList use virtualized rendering, which helps reduce the number of rows mounted at the same time. Correct data updates and lightweight row components are still important for smooth scrolling.
1. Use Stable Keys
Provide unique keys so React can identify rows accurately when the data changes.
2. Keep Row Components Lightweight
Avoid expensive calculations and unnecessary nested components inside each row. Extract complex item UI into reusable components when it improves maintainability.
3. Use getItemLayout for Fixed-Size Rows
If every row has a predictable size, getItemLayout can avoid some layout measurements and improve certain scrolling operations.
const ITEM_HEIGHT = 60;
<FlatList
data={items}
keyExtractor={item => item.id}
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index
})}
renderItem={({ item }) => (
<Text style={{ height: ITEM_HEIGHT, padding: 12 }}>
{item.title}
</Text>
)}
/>
Use this approach only when item dimensions are predictable. If separators add to the row spacing, include their dimensions in the offset calculation.
4. Avoid Unnecessary Re-Renders
Use stable callbacks and memoized row components when profiling shows a benefit. Ensure state changes produce the expected new data and props rather than mutating existing data in place.
5. Configure the Initial Render Count
The initialNumToRender prop controls how many items are rendered initially. Choose a value sufficient to fill the first screen without doing unnecessary work.
6. Understand Virtualization
Rows may be rendered asynchronously as they enter the render window. Internal component state is not guaranteed to survive when a row scrolls outside that window. Keep important item state in the data model or an appropriate external store.
For more details, read the official FlatList reference and SectionList reference.
25. Common Errors and Troubleshooting
| Problem |
Possible Cause |
Solution |
| Items do not appear. |
Incorrect data structure or missing renderItem. |
Check the data array and ensure renderItem returns valid components. |
| Missing key warning. |
Rows lack stable unique keys. |
Provide a suitable keyExtractor. |
| List does not update. |
Data was mutated or external state was not passed to the list. |
Use immutable updates and extraData where appropriate. |
| Section headings are missing. |
Incorrect section data or missing renderSectionHeader. |
Pass a sections array containing data arrays and configure the header renderer. |
| Repeated items appear. |
Pagination is triggered repeatedly or pages overlap. |
Prevent concurrent requests and deduplicate items when necessary. |
| Scrolling is slow. |
Rows are expensive to render or images are too large. |
Profile rendering and optimize the item components and images. |
| Empty message appears during loading. |
Loading and empty states are not separated. |
Track loading, error, and empty states independently. |
| Scroll-to-index fails. |
Target item is outside the render window or its dimensions are unknown. |
Provide layout information or handle scroll-to-index failure. |
| Section keys are unstable. |
Sections are reordered without stable identifiers. |
Provide stable section keys when section order can change. |
26. Best Practices for FlatList and SectionList
- Choose FlatList for a single collection and SectionList for grouped data.
- Use stable unique keys for rows and sections when appropriate.
- Keep row components focused and easy to maintain.
- Provide useful empty-state messages.
- Use headers, footers, and separators to improve readability.
- Keep loading, empty, and error states distinct.
- Update list data immutably through React state.
- Use extraData when external state affects row rendering.
- Protect pagination from duplicate requests.
- Use getItemLayout only when dimensions are known.
- Test on Android and iOS, including smaller screens.
- Provide accessible labels and clear interaction feedback.
- Measure performance before applying advanced optimizations.
27. Practical Project: Course Directory
Build a course directory using SectionList. Each section represents a learning category, and each row displays the course title and duration.
Sample Data
const courseSections = [
{
title: 'Mobile Development',
data: [
{ id: '1', title: 'React Native', duration: '6 weeks' },
{ id: '2', title: 'Flutter', duration: '6 weeks' }
]
},
{
title: 'Web Development',
data: [
{ id: '3', title: 'React JS', duration: '5 weeks' },
{ id: '4', title: 'HTML and CSS', duration: '4 weeks' }
]
},
{
title: 'Data Analytics',
data: [
{ id: '5', title: 'Power BI', duration: '5 weeks' },
{ id: '6', title: 'Basic SQL', duration: '4 weeks' }
]
}
];
Project Requirements
- Display each category as a section heading.
- Show each course title and duration.
- Use stable IDs for individual courses.
- Add separators between rows.
- Display a message when no courses are available.
- Make rows pressable to open course details.
- Use consistent styling for headings and items.
- Test scrolling and layout on different screen sizes.
Suggested Implementation
import React from 'react';
import {
View,
Text,
SectionList,
Pressable,
StyleSheet
} from 'react-native';
const courseSections = [
{
title: 'Mobile Development',
data: [
{ id: '1', title: 'React Native', duration: '6 weeks' },
{ id: '2', title: 'Flutter', duration: '6 weeks' }
]
},
{
title: 'Web Development',
data: [
{ id: '3', title: 'React JS', duration: '5 weeks' },
{ id: '4', title: 'HTML and CSS', duration: '4 weeks' }
]
}
];
export default function CourseDirectory() {
return (
<View style={styles.container}>
<SectionList
sections={courseSections}
keyExtractor={item => item.id}
stickySectionHeadersEnabled
renderSectionHeader={({ section }) => (
<Text style={styles.sectionHeader}>
{section.title}
</Text>
)}
renderItem={({ item }) => (
<Pressable
style={styles.courseRow}
onPress={() => {
// Add navigation to course details here.
}}
accessibilityRole="button"
accessibilityLabel={`${item.title}, ${item.duration}`}
>
<View>
<Text style={styles.courseTitle}>
{item.title}
</Text>
<Text style={styles.duration}>
Duration: {item.duration}
</Text>
</View>
</Pressable>
)}
ItemSeparatorComponent={() => (
<View style={styles.separator} />
)}
ListEmptyComponent={
<Text style={styles.empty}>No courses available.</Text>
}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
backgroundColor: '#FFFFFF'
},
sectionHeader: {
padding: 12,
fontSize: 18,
fontWeight: 'bold',
backgroundColor: '#E5E7EB'
},
courseRow: {
padding: 14
},
courseTitle: {
fontSize: 16,
fontWeight: '600'
},
duration: {
marginTop: 5,
color: '#4B5563'
},
separator: {
height: 1,
backgroundColor: '#D1D5DB'
},
empty: {
padding: 20,
textAlign: 'center'
}
});
This project combines grouped data, section headers, item rendering, separators, empty-state handling, accessibility labels, and a place to add navigation logic.
28. Practice Exercises
- Student List: Display ten students using FlatList with each student's name and class.
- Product Grid: Display products in two columns using numColumns.
- Contact Directory: Group contacts alphabetically using SectionList.
- Task Manager: Add a remove action to each row and update the list state.
- Search Results: Filter FlatList data based on a search query.
- Empty State: Display a useful message when the list contains no items.
- Refreshable Feed: Add pull-to-refresh and a refreshing indicator.
- Pagination: Load more records when the user approaches the bottom.
- Selection UI: Highlight a selected item and update the UI correctly.
- Course Directory: Create a SectionList grouped by subject and show course durations.
29. Interview Questions and Answers
Q1. What is FlatList in React Native?
Answer: FlatList is a built-in component for rendering scrollable collections of similarly structured data using virtualized rendering.
Q2. What is SectionList?
Answer: SectionList displays items grouped into sections, each of which can have a heading and its own list of items.
Q3. What is the main difference between FlatList and SectionList?
Answer: FlatList renders a single collection, whereas SectionList renders collections grouped into sections.
Q4. What are data and renderItem?
Answer: The data prop supplies the items, and renderItem defines how each item is displayed.
Q5. Why is keyExtractor used?
Answer: It returns a key that React uses to identify items between renders. Stable unique keys help React track changes correctly.
Q6. How do you add a heading to a SectionList section?
Answer: Use renderSectionHeader and access the current section through its section argument.
Q7. How do you add a separator between rows?
Answer: Use ItemSeparatorComponent to render a divider between list items.
Q8. What is ListEmptyComponent?
Answer: It displays content when the list has no items to render.
Q9. What does numColumns do?
Answer: It lets FlatList display items in multiple columns, commonly for grid layouts.
Q10. How do you implement pull-to-refresh?
Answer: Provide an onRefresh handler and control the refresh indicator through the refreshing prop.
Q11. What is onEndReached used for?
Answer: It allows an application to trigger an action when the user approaches the end of the list, such as loading another page of results.
Q12. Why might a list not update after state changes?
Answer: Data may have been mutated in place or an external state dependency may not be reflected in the list props. Use immutable updates and extraData where appropriate.
Q13. What is getItemLayout?
Answer: It provides known item dimensions and offsets so the list can skip some measurement work and improve certain scrolling operations.
Q14. What are sticky section headers?
Answer: They remain visible near the top while the user scrolls through a section, until another header replaces them.
Q15. Why are FlatList and SectionList useful for large collections?
Answer: Their virtualized rendering approach can reduce the number of mounted rows compared with rendering every item inside a ScrollView.
30. Quick Revision Checklist
- Know when to use FlatList and SectionList.
- Understand the data and renderItem props.
- Use keyExtractor for stable item keys.
- Use renderSectionHeader for grouped lists.
- Style rows with View, Text, Pressable, and StyleSheet.
- Add separators, headers, footers, and empty-state messages.
- Understand horizontal lists and multi-column grids.
- Update list data immutably through React state.
- Use extraData when external state affects rendering.
- Implement pull-to-refresh and pagination when required.
- Optimize list rendering when needed.
- Test accessibility, scrolling, and platform-specific behavior.
31. Official Documentation and Learning Resources
32. Conclusion
FlatList and SectionList are essential components for building list-based interfaces in React Native. FlatList is ideal for displaying a single collection, while SectionList is better suited to data organized into groups with headings.
By learning list data structures, item rendering, key extraction, separators, empty states, interactions, state updates, refreshing, pagination, and performance optimization, you can build maintainable list interfaces for real-world mobile applications.
Practice the examples and exercises in these notes to develop confidence in building simple lists, grouped directories, product grids, and dynamic feeds.
Explore more: React Native Training Course | Register for a Demo | JustAcademy